package com.cqfae.deploycentral.app.services.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqfae.deploycentral.api.utils.IdGenerator;
import com.cqfae.deploycentral.app.base.BaseConstantCode;
import com.cqfae.deploycentral.app.base.BaseConstants;
import com.cqfae.deploycentral.app.config.FilePathInfo;
import com.cqfae.deploycentral.app.config.JiraIssues;
import com.cqfae.deploycentral.app.config.JobExecuteInfo;
import com.cqfae.deploycentral.app.config.TestLinkInfo;
import com.cqfae.deploycentral.app.dao.entity.*;
import com.cqfae.deploycentral.app.dao.mapper.*;
import com.cqfae.deploycentral.app.job.JiraJob;
import com.cqfae.deploycentral.app.job.TestLinkJob;
import com.cqfae.deploycentral.app.services.ExpectPublishEnqueueService;
import com.cqfae.deploycentral.app.services.JiraService;
import com.cqfae.deploycentral.app.services.ReportInfoService;
import com.cqfae.deploycentral.app.utils.*;
import com.cqfae.deploycentral.app.web.enums.LimitStatusEnum;
import com.cqfae.deploycentral.app.web.request.ReportInfoRequest;
import com.cqfae.deploycentral.app.web.response.IPage;
import com.cqfae.deploycentral.app.web.response.JiraInfo;
import com.cqfae.deploycentral.app.web.vo.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.gson.reflect.TypeToken;
import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.Header;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * Created by yangheng940 on 2017/7/11.
 */
@Service
@Transactional
public class ReportInfoServiceImpl implements ReportInfoService {

    private static Logger logger = LoggerFactory.getLogger(ReportInfoServiceImpl.class);

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private ReportInfoMapper reportInfoMapper;

    @Autowired
    private ReportInfoTagMapper reportInfoTagMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private JobExecuteInfo jobExecuteInfo;

    @Autowired
    private TestLinkInfo testLinkInfo;

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private AppInfoMapper appInfoMapper;


    @Autowired
    private WindowPlansMapper windowPlansMapper;

    @Autowired
    private WindowPlansTagMapper windowPlansTagMapper;

    @Autowired
    private WindowInfoMapper windowInfoMapper;

    @Autowired
    private ReportTestLinkMapper reportTestLinkMapper;

    private String sqlReportCode = "reportCode";

    private String sqlCreateTimeDesc = "CREATE_TIME DESC";

    private String sqlVersionId = "versionId";

    private String sqlTitle = "title";

    private String NO_USE = "no_use";

    @Autowired
    private ExpectPublishEnqueueService expectPublishEnqueueService;

    @Autowired
    private ExpectPublishEnqueueMapper expectPublishEnqueueMapper;

    @Autowired
    private JiraService jiraService;

    @Autowired
    private ReportJiraMapper reportJiraMapper;

    @Autowired
    private JobHistoryMapper jobHistoryMapper;

    @Autowired
    private ReportFilesMapper reportFilesMapper;

    @Autowired
    private FilePathInfo filePathInfo;

    @Autowired
    private ConvertUtil convertUtil;

    @Override
    public IPage<ReportInfoVo> page(ReportInfoRequest request) {
        // 查询版本号对应report
        List<String> reportCodeList = new ArrayList<>();
        if (StringUtils.isNotBlank(request.getVersionNameQuery())) {
            Example exampleReport = new Example(ReportTestLink.class);
            exampleReport.createCriteria().andLike("versionName", "%" + request.getVersionNameQuery() + "%");
            List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.selectByExample(exampleReport);
            for (ReportTestLink reportTestLink : reportTestLinkList) {
                reportCodeList.add(reportTestLink.getReportCode());
            }
        }

        Page<ReportInfoVo> page = PageHelper.startPage(request.getPageNum(), request.getPageSize());
        Example example = new Example(ReportInfo.class);
        example.setOrderByClause(sqlCreateTimeDesc);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(request.getTitle())) {
            criteria.andLike(sqlTitle, "%" + request.getTitle() + "%");
        }
        if (StringUtil.isNotEmpty(request.getPersonal())) {
            criteria.andEqualTo("createBy", "123");
        }

        if (StringUtils.isNotBlank(request.getVersionNameQuery())) {
            if (!reportCodeList.isEmpty()) {
                criteria.andIn(sqlReportCode, reportCodeList);
            } else {
                return ConvertUtil.pageToIpage(page, new IPage<ReportInfoVo>());
            }
        }
        reportInfoMapper.selectByExample(example);
        IPage<ReportInfoVo> iPage = ConvertUtil.pageToIpage(page, new IPage<ReportInfoVo>());
        List<ReportInfoVo> result = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(page), new TypeToken<List<ReportInfoVo>>() {
        }.getType());
        if (result != null && !result.isEmpty()) {
            for (ReportInfoVo reportInfoVo : result) {
                String status = String.valueOf(reportInfoVo.getReportStatus());
                reportInfoVo.setReportStatusStr(BaseConstants.getConstantsCodeMap().get(status));
            }
        }
        iPage.setResult(result);
        return iPage;
    }

    @Override
    public List<ReportInfo> pageList(ReportInfoRequest request) {
        Page<ReportInfo> page = PageHelper.startPage(request.getPageNum(), request.getPageSize());
        Example example = new Example(ReportInfo.class);
        example.setOrderByClause(sqlCreateTimeDesc);
        example.createCriteria().andEqualTo(sqlReportCode, request.getReportCode());
        reportInfoMapper.selectByExample(example);
        return GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(page), new TypeToken<List<ReportInfo>>() {
        }.getType());
    }

    @Override
    public Integer save(ReportInfoVo vo) {
        // 标题验证
        Assert.isTrue(!isRepeat(vo.getTitle(), null), "标题重复，请修改");

        // 获取reportCode
        String reportCode = DateFormatUtils.format(new Date(),
                BaseConstants.DATE_NUMBER_FORMAT) + RandomStringUtils.randomNumeric(3);

        // 保存TESTLINK信息，并启动job
        List<ReportTestLinkVo> reportTestLinkVoList = vo.getReportTestLinkVoList();
        insertTestLinkAndCreateJob(reportTestLinkVoList, reportCode, vo.getTitle());

        ReportInfo entity = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(vo), ReportInfo.class);
        entity.setId(idGenerator.nextId());
        entity.setReportCode(reportCode);
        entity.setReportStatus(BaseConstantCode.REPORT_STATUS_INIT);
        entity.setCreateBy("123");
        entity.setCreateTime(new Date());
        entity.setUpdateBy("123");
        entity.setUpdateTime(new Date());
        int i = reportInfoMapper.insertSelective(entity);
        // 测试报告插入异常
        Assert.isTrue(i == 1, "新增测试报告数据异常");

        // 插入待发布
        ExpectPublishEnqueue expectPublishEnqueue = new ExpectPublishEnqueue();
        expectPublishEnqueue.setReportCode(reportCode);
        expectPublishEnqueue.setTestStatus(String.valueOf(BaseConstantCode.REPORT_STATUS_INIT));
        expectPublishEnqueueService.save(expectPublishEnqueue);

        return i;
    }

    /**
     * 根据ID更新测试报告及其TAG、require
     * 更新内容不包括测试报告状态，其他属性却可以修改
     * 测试报告的从数据只能修改，不能新增或者删除
     *
     * @param vo
     * @return
     */
    @Override
    public Integer edit(ReportInfoVo vo) {
        // 标题验证
        Assert.isTrue(!isRepeat(vo.getTitle(), vo.getReportCode()), "标题重复，请修改");

        // check测试报告是否有ID
        Assert.isTrue(vo.getId() != null, "测试报告ID为空");
        // 查询测试报告code
        ReportInfo reportInfo = new ReportInfo();
        reportInfo.setId(vo.getId());
        reportInfo = reportInfoMapper.selectOne(reportInfo);
        Assert.isTrue(null != reportInfo, "测试报告不存在");
        vo.setReportCode(reportInfo.getReportCode());

        Example exampleReportTestLink = new Example(ReportTestLink.class);
        // 保存需要新增、删除的reportTestLink
        exampleReportTestLink.clear();
        exampleReportTestLink.createCriteria().andEqualTo(sqlReportCode, reportInfo.getReportCode());
        List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.selectByExample(exampleReportTestLink);
        List<ReportTestLink> reportTestLinkVoListDelete = new ArrayList<>(reportTestLinkList);
        // 更新reportTestLink
        List<ReportTestLinkVo> reportTestLinkVoList = vo.getReportTestLinkVoList();

        for (ReportTestLinkVo reportTestLinkVo : reportTestLinkVoList) {
            for (ReportTestLink reportTestLink : reportTestLinkList) {
                if (reportTestLinkVo.getTprjname().equals(reportTestLink.getTprjname())
                        && reportTestLinkVo.getVersionId().longValue() == reportTestLink.getVersionId().longValue()) {
                    // 存在且没有修改的，不操作
                    reportTestLinkVoListDelete.remove(reportTestLink);
                }
            }
        }

        // 更新测试负责人
        updateTestJiraLeader(vo.getReportJiraVoList(), reportInfo.getReportCode());

        // 删除REPORTTESTLINK、删除REPORTJIRA信息,停止job
        Example exampleReportJira = new Example(ReportJira.class);
        for (ReportTestLink reportTestLink : reportTestLinkVoListDelete) {
            String reportCode = reportTestLink.getReportCode();
            exampleReportTestLink.clear();
            exampleReportTestLink.createCriteria().andEqualTo("tprjname", reportTestLink.getTprjname())
                    .andEqualTo(sqlVersionId, reportTestLink.getVersionId());
            // 删除REPORTTESTLINK测试报告关系
            ReportTestLink reportTestLinkUpdate = new ReportTestLink();
            reportTestLinkUpdate.setReportCode(NO_USE);
            reportTestLinkMapper.updateByExampleSelective(reportTestLinkUpdate, exampleReportTestLink);
            // 删除REPORTJIRA信息
            exampleReportJira.clear();
            exampleReportJira.createCriteria().andEqualTo(sqlReportCode, reportCode)
                    .andEqualTo(sqlVersionId, reportTestLink.getVersionId());
            reportJiraMapper.deleteByExample(exampleReportJira);
        }

        // 关闭TESTLINK相关job
        closeJob(jobExecuteInfo.getJobInfoTestLink().getJobName(), jobExecuteInfo.getJobInfoTestLink().getGroupName(), reportInfo.getReportCode());
        // 关闭JIRA相关job
        closeJob(jobExecuteInfo.getJobInfoJira().getJobName(), jobExecuteInfo.getJobInfoJira().getGroupName(), reportInfo.getReportCode());
        // 新增TESTLINK，job
        insertTestLinkAndCreateJob(reportTestLinkVoList, reportInfo.getReportCode(), vo.getTitle());

        // 获取TAG信息
        List<ReportInfoTagVo> reportInfoTagVoList = vo.getReportInfoTagsVoList();
        // 更新或者插入ReportTag
        updateOrInsertReportTag(reportInfoTagVoList, vo.getReportCode());

        // 当该测试报告已存在对应的windowPlan时，更新对应windowPlanTag
        Example exampleWindowPlans = new Example(WindowPlans.class);
        exampleWindowPlans.createCriteria().andEqualTo(sqlReportCode, vo.getReportCode());
        List<WindowPlans> windowPlansList = windowPlansMapper.selectByExample(exampleWindowPlans);
        if (windowPlansList != null && windowPlansList.size() == 1) {
            // 删除现有windowPlansTag
            Example exampleWindowPlansTag = new Example(WindowPlansTag.class);
            exampleWindowPlansTag.createCriteria().andEqualTo(sqlReportCode, vo.getReportCode());
            windowPlansTagMapper.deleteByExample(exampleWindowPlansTag);
            // 重新插入windowPlansTag
            ReportInfoTag reportInfoTag = new ReportInfoTag();
            reportInfoTag.setReportCode(vo.getReportCode());
            List<ReportInfoTag> reportInfoTagList = getReportInfoTagList(reportInfoTag);
            for (ReportInfoTag reportInfoTag1 : reportInfoTagList) {
                WindowPlansTag tag = new WindowPlansTag();
                tag.setId(idGenerator.nextId());
                tag.setWindowPlansId(windowPlansList.get(0).getId());
                tag.setReportCode(vo.getReportCode());
                tag.setReportTagId(reportInfoTag1.getId());
                tag.setDeployStatus(BaseConstantCode.DEPLOY_STATUS_NOBUILD);
                tag.setLimitStatus(LimitStatusEnum.NOT_LIMIT_STATUS.getCode());
                tag.setCreateBy("123");
                tag.setCreateTime(new Date());
                windowPlansTagMapper.insertSelective(tag);
            }
        }

        // 将vo转换成bean
        ReportInfo entity = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(vo), ReportInfo.class);
        // 设置更新人和时间
        entity.setUpdateBy("123");
        entity.setUpdateTime(new Date());
        // TESTLINK相关数据出现修改时，这四个字段清空
        if (reportTestLinkVoListDelete != null && !reportTestLinkVoListDelete.isEmpty()) {
            entity.setSitResult("");
            entity.setRetResult("");
            entity.setUatResult("");
            entity.setBugRemark("");
        }

        // 操作测试报告文件
        operateReportFile(reportInfo.getReportCode(), vo.getFileList());

        // 更新唯一条件id
        Example example = new Example(ReportInfo.class);
        example.createCriteria().andEqualTo("id", entity.getId());
        return reportInfoMapper.updateByExampleSelective(entity, example);
    }

    /**
     * 操作测试报告文件
     *
     * @param reportCode
     * @param fileUploadVoList
     */
    private void operateReportFile(String reportCode, List<FileUploadVo> fileUploadVoList) {
        Example example = new Example(ReportFiles.class);
        // 删除数据库
        example.createCriteria().andEqualTo(sqlReportCode, reportCode);
        reportFilesMapper.deleteByExample(example);

        ReportFiles reportFiles = new ReportFiles();
        reportFiles.setReportCode(reportCode);
        // 更新测试报告文件
        if (fileUploadVoList != null && !fileUploadVoList.isEmpty()) {
            for (FileUploadVo fileUploadVo : fileUploadVoList) {
                // 数据库新增
                reportFilesAdd(reportCode, fileUploadVo);
            }
        }
    }

    /**
     * 新增
     *
     * @param reportCode
     * @param fileUploadVo
     */
    private void reportFilesAdd(String reportCode, FileUploadVo fileUploadVo) {
        String fileName = "";
        try {
            fileName = fileUploadVo.getFileName();
            fileName = fileName.substring(fileName.indexOf('>') + 1);
            fileName = fileName.substring(0, fileName.indexOf('<'));
        } catch (Exception e) {
            logger.error("reportFilesAdd subString error", e);
            Assert.isTrue(false, "");
        }

        // 更新reportFile
        ReportFiles reportFiles1 = new ReportFiles();
        reportFiles1.setReportCode(reportCode);
        reportFiles1.setFileUrl(filePathInfo.getReportPath() + File.separator + reportCode);
        reportFiles1.setFileName(fileName);
        reportFiles1.setFileType(fileUploadVo.getFileType());
        reportFiles1.setCreateBy("123");
        reportFiles1.setCreateTime(new Date());
        reportFiles1.setId(idGenerator.nextId());
        reportFilesMapper.insertSelective(reportFiles1);

        // 存在ID的情况为曾今上传，这次略
        if (fileUploadVo.getFileId() != null && !fileName.equals(fileUploadVo.getFileId())) {
            return;
        } else {
            // 测试报告上传路径
            String fileRealPath = filePathInfo.getReportPath() + File.separator + reportCode + File.separator + fileUploadVo.getFileId();
            if (!DCFileUtil.fileMove(filePathInfo.getReportPath() + fileUploadVo.getFilePath(), fileRealPath)) {
                Assert.isTrue(false, "文件上传失败");
            }
        }

    }

    @Override
    public Integer deleteOneTag(Long id) {
        ReportInfoTag reportInfoTag = new ReportInfoTag();
        reportInfoTag.setId(id);
        return reportInfoTagMapper.delete(reportInfoTag);
    }

    @Override
    public List<ReportInfo> findAll() {
        return reportInfoMapper.selectAll();
    }

    @Override
    public ReportInfoVo getOne(ReportInfoRequest request) {
        if (NullUtil.isNotEmpty(request.getReportCode())) {
            ReportInfo entity = new ReportInfo();
            entity.setReportCode(request.getReportCode());
            entity = reportInfoMapper.selectOne(entity);
            // 测试报告存在时查找附属信息，不存在时不查找
            if (entity != null) {
                ReportInfoVo vo = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(entity), ReportInfoVo.class);
                // 查询reportTestLink
                Example exampleTestLink = new Example(ReportTestLink.class);
                exampleTestLink.orderBy(sqlCreateTimeDesc).desc();
                exampleTestLink.createCriteria().andEqualTo("reportCode", request.getReportCode());
                List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.selectByExample(exampleTestLink);
                List<ReportTestLinkVo> reportTestLinkVoList = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(reportTestLinkList),
                        new TypeToken<List<ReportTestLinkVo>>() {
                        }.getType());
                vo.setReportTestLinkVoList(reportTestLinkVoList);

                // 查询reportJira
                ReportJira reportJira = new ReportJira();
                reportJira.setReportCode(request.getReportCode());
                List<ReportJira> reportJiraList = reportJiraMapper.select(reportJira);
                List<ReportJiraVo> reportJiraVoList = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(reportJiraList),
                        new TypeToken<List<ReportJiraVo>>() {
                        }.getType());
                vo.setReportJiraVoList(reportJiraVoList);

                // 设置testlink名称
                Map map = new HashMap();
                for (ReportTestLink reportTestLink1 : reportTestLinkList) {
                    map.put(reportTestLink1.getVersionId(), reportTestLink1.getTprjname());
                }
                for (ReportJiraVo reportJiraVo : reportJiraVoList) {
                    reportJiraVo.setTprjname((String) map.get(reportJiraVo.getVersionId()));
                }

                // 设置测试报告TAG
                ReportInfoTag reportInfoTag = new ReportInfoTag();
                reportInfoTag.setReportCode(request.getReportCode());
                // 优先级升序排序查询
                List<ReportInfoTag> reportInfoTagsList = getReportInfoTagList(reportInfoTag);
                List<ReportInfoTagVo> reportInfoTagVoList = GsonUtils.getInstance().fromJson(GsonUtils.getInstance().toJson(reportInfoTagsList), new TypeToken<List<ReportInfoTagVo>>() {
                }.getType());
                vo.setReportInfoTagsVoList(reportInfoTagVoList);

                Example exampleWindowPlans = new Example(WindowPlans.class);
                exampleWindowPlans.createCriteria().andEqualTo(sqlReportCode, request.getReportCode());
                List<WindowPlans> windowPlansList = windowPlansMapper.selectByExample(exampleWindowPlans);
                if (windowPlansList != null && windowPlansList.size() == 1) {
                    Example exampleWindowInfo = new Example(WindowInfo.class);
                    exampleWindowInfo.createCriteria().andEqualTo("windowDate", windowPlansList.get(0).getWindowDate());
                    List<WindowInfo> windowInfoList = windowInfoMapper.selectByExample(exampleWindowInfo);
                    if (windowInfoList != null && windowInfoList.size() == 1) {
                        vo.setLocked(windowInfoList.get(0).getLocked());
                    }
                } else {
                    vo.setLocked(BaseConstantCode.WINDOW_OPEN);
                }

                // reportFiles设置
                List<FileUploadVo> fileUploadVoList = new ArrayList<>();
                ReportFiles reportFiles = new ReportFiles();
                reportFiles.setReportCode(entity.getReportCode());
                List<ReportFiles> reportFilesList = reportFilesMapper.select(reportFiles);
                for (ReportFiles reportFiles1 : reportFilesList) {
                    FileUploadVo fileUploadVo = new FileUploadVo();
                    fileUploadVo.setFileId(String.valueOf(reportFiles1.getId()));
                    fileUploadVo.setFileName(reportFiles1.getFileName());
                    fileUploadVo.setFilePath(reportFiles1.getFileUrl());
                    fileUploadVo.setFileType(reportFiles1.getFileType());
                    fileUploadVoList.add(fileUploadVo);
                }
                vo.setFileList(fileUploadVoList);

                return vo;
            }
        }
        return null;
    }

    @Override
    public List<SelectedVo> getSelectedList(ReportInfoRequest request) {
        Example example = new Example(ReportInfo.class);
        example.setOrderByClause(sqlCreateTimeDesc);
        example.createCriteria().andEqualTo("reportStatus", BaseConstantCode.REPORT_STATUS_INIT);
        List<ReportInfo> result = reportInfoMapper.selectByExample(example);
        List<SelectedVo> selectedList = new ArrayList<>();
        for (ReportInfo info : result) {
            SelectedVo vo = new SelectedVo(info.getReportCode(), info.getTitle());
            selectedList.add(vo);
        }
        return selectedList;
    }

    @Override
    public List<SelectedVo> getReportSelected(ReportInfoRequest request) {
        Example example = new Example(ReportInfo.class);
        example.setOrderByClause(sqlCreateTimeDesc);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("reportStatus", BaseConstantCode.REPORT_STATUS_INIT);
        if (StringUtils.isNotBlank(request.getQuery())) {
            criteria.andLike(sqlTitle, "%" + request.getQuery() + "%");
        }
        List<ReportInfo> reportInfoList = reportInfoMapper.selectByExample(example);
        List<SelectedVo> selectedList = new ArrayList<>();
        for (ReportInfo info : reportInfoList) {
            SelectedVo vo = new SelectedVo(info.getReportCode(), info.getTitle());
            selectedList.add(vo);
        }
        return selectedList;
    }

    /**
     * 根据reportCode获得ReportInfoTag
     *
     * @param reportInfoTag
     * @return
     */
    @Override
    public List<ReportInfoTag> getReportInfoTagList(ReportInfoTag reportInfoTag) {
        // 以优先级升序的结果排序
        Example example = new Example(ReportInfoTag.class);
        example.orderBy("level");
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(sqlReportCode, reportInfoTag.getReportCode());
        if (reportInfoTag.getId() != null) {
            criteria.andEqualTo("id", reportInfoTag.getId());
        }
        return reportInfoTagMapper.selectByExample(example);
    }

    /**
     * 获取testLink数据
     *
     * @return
     */
    @Override
    public List<SelectedVo> getTestLink(String reportCode) {
        List<SelectedVo> selectedVoList = new ArrayList<>();
        // 访问url获取数据
        String url = testLinkInfo.getHost() + testLinkInfo.getGetprojects();
        logger.info("ReportInfoServiceImpl.getTestLink call url:{}", url);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url,
                HttpMethod.GET, null, String.class);
        String responseEntityStr = GsonUtils.getInstance().toJson(responseEntity);
        logger.info("ReportInfoServiceImpl.getTestLink return result:{}", responseEntityStr);
        String bodyStr = responseEntity.getBody();
        JSONObject bodyJson = JSONObject.parseObject(bodyStr);
        // 数据转换
        if (bodyJson != null && !bodyJson.isEmpty()) {
            JSONArray bodyJsonArray = (JSONArray) bodyJson.get("projects");
            if (bodyJsonArray != null && !bodyJsonArray.isEmpty()) {
                for (int i = 0; i < bodyJsonArray.size(); i++) {
                    JSONObject jsonObject = (JSONObject) bodyJsonArray.get(i);
                    String code = String.valueOf(jsonObject.get("id"));
                    String name = String.valueOf(jsonObject.get("name"));

                    SelectedVo selectedVo = new SelectedVo();
                    selectedVo.setCode(code);
                    selectedVo.setName(name);
                    selectedVoList.add(selectedVo);

                }
            }
        }
        return selectedVoList;
    }


    /**
     * 获取JIRA数据
     *
     * @return
     */
    public List<SelectedVo> getJiraVersion(String reportCode) {
        List<SelectedVo> selectedVoList = new ArrayList<>();

        // 获取所有用过Jira号,不包括当前parentCode使用的
        Map map = new HashMap();
        Example example = new Example(ReportTestLink.class);
        example.createCriteria().andNotEqualTo(sqlReportCode, NO_USE);
        List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.selectByExample(example);
        if (reportTestLinkList != null && !reportTestLinkList.isEmpty()) {
            for (ReportTestLink reportTestLink : reportTestLinkList) {
                if (reportTestLink.getReportCode().equals(reportCode)) {
                    SelectedVo selectedVo = new SelectedVo();
                    selectedVo.setCode(String.valueOf(reportTestLink.getVersionId()));
                    selectedVo.setName(reportTestLink.getVersionName());
                    selectedVoList.add(selectedVo);
                }
                map.put(reportTestLink.getVersionId(), reportTestLink.getVersionId());

            }
        }

        List<JiraInfo> jiraInfoList = jiraService.getReadyForReleasedVersion();
        if (jiraInfoList != null && !jiraInfoList.isEmpty()) {
            for (JiraInfo jiraInfo : jiraInfoList) {
                if (map.get(jiraInfo.getVersionId()) == null) {
                    SelectedVo selectedVo = new SelectedVo();
                    selectedVo.setCode(String.valueOf(jiraInfo.getVersionId()));
                    selectedVo.setName(jiraInfo.getName());
                    selectedVoList.add(selectedVo);
                }
            }
        }

        return selectedVoList;
    }

    /**
     * 根据reportCode获取版本ID
     *
     * @param reportCode
     * @return
     */
    @Override
    public List<ReportTestLink> getReportTestLink(String reportCode) {
        Example example = new Example(ReportTestLink.class);
        example.createCriteria().andEqualTo(sqlReportCode, reportCode);
        return reportTestLinkMapper.selectByExample(example);
    }

    /**
     * 提交至待发布
     *
     * @param reportInfoVo
     * @return
     */
    @Override
    public int commitPublic(ReportInfoVo reportInfoVo) {
        //先保存
        this.edit(reportInfoVo);

        String reportCode = reportInfoVo.getReportCode();
        // 保存是否查询jira
        boolean isQueryJira = false;
        // 判断version的story是否全部完成
        Example example = new Example(ReportJira.class);
        example.createCriteria().andEqualTo(sqlReportCode, reportCode);
        List<ReportJira> reportJiraList = reportJiraMapper.selectByExample(example);
        if (reportJiraList != null && !reportJiraList.isEmpty()) {
            // 查询所有版本状态
            for (ReportJira reportJira : reportJiraList) {
                if (!reportJira.getIssuesStatus().equalsIgnoreCase(BaseConstants.getConstantsCodeMap().get("jiraStatus.readyForRelease"))) {
                    isQueryJira = true;
                    break;
                }
            }
        } else {
            isQueryJira = true;
        }
        // 本地jira显示未完成，查询jira系统
        if (isQueryJira) {
            // 判断测试报告是否完成，完成后更新reportJira
            isDoneJira(reportCode);
        }

        // 关闭TESTLINK相关job
        closeJob(jobExecuteInfo.getJobInfoTestLink().getJobName(), jobExecuteInfo.getJobInfoTestLink().getGroupName(), reportCode);
        // 关闭JIRA相关job
        closeJob(jobExecuteInfo.getJobInfoJira().getJobName(), jobExecuteInfo.getJobInfoJira().getGroupName(), reportCode);

        // 更新reportInfo状态
        ReportInfo reportInfo = new ReportInfo();
        reportInfo.setReportStatus(BaseConstantCode.REPORT_STATUS_WPUBLISH);
        reportInfo.setUpdateBy("123");
        reportInfo.setUpdateTime(new Date());
        reportInfo.setSitTimeEnd(reportInfoVo.getSitTimeEnd());
        reportInfo.setRetTimeEnd(reportInfoVo.getRetTimeEnd());
        Example exampleReportInfo = new Example(ReportInfo.class);
        exampleReportInfo.createCriteria().andEqualTo(sqlReportCode, reportCode);
        int count = reportInfoMapper.updateByExampleSelective(reportInfo, exampleReportInfo);

        // 更新t_expect_publish_enqueue
        ExpectPublishEnqueue expectPublishEnqueue = new ExpectPublishEnqueue();
        expectPublishEnqueue.setTestStatus(String.valueOf(BaseConstantCode.REPORT_STATUS_WPUBLISH));
        expectPublishEnqueue.setUpdateBy("123");
        expectPublishEnqueue.setUpdateTime(new Date());
        Example exampleExpectPublishEnqueue = new Example(ExpectPublishEnqueue.class);
        exampleExpectPublishEnqueue.createCriteria().andEqualTo(sqlReportCode, reportCode);
        expectPublishEnqueueMapper.updateByExampleSelective(expectPublishEnqueue, exampleExpectPublishEnqueue);

        return count;
    }

    /**
     * 判断测试报告是否完成，完成后更新reportJira
     *
     * @param reportCode
     */
    private void isDoneJira(String reportCode) {
        // 查询versionId
        ReportTestLink reportTestLink = new ReportTestLink();
        reportTestLink.setReportCode(reportCode);
        List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.select(reportTestLink);
        // 查询JIRA数据
        if (reportTestLinkList != null && !reportTestLinkList.isEmpty()) {
            for (ReportTestLink reportTestLink1 : reportTestLinkList) {
                Long versionId = reportTestLink1.getVersionId();
                JiraInfo jiraInfo = jiraService.getOneInfoReVersion(versionId);
                if (jiraInfo != null) {
                    List<JiraIssues> jiraIssuesList = jiraInfo.getIssuesList();
                    if (jiraIssuesList != null && !jiraIssuesList.isEmpty()) {
                        for (JiraIssues jiraIssues : jiraIssuesList) {

                            // 筛选story
                            if (!jiraIssues.getTypeName().equalsIgnoreCase(BaseConstants.getConstantsCodeMap().get("jiraStatus.bug"))) {
                                if (!jiraIssues.getIssuesStatu().equalsIgnoreCase(BaseConstants.getConstantsCodeMap().get("jiraStatus.readyForRelease"))) {
                                    Assert.isTrue(false, "测试报告版本任务未完成");
                                } else {
                                    Example exampleReportJira = new Example(ReportJira.class);
                                    exampleReportJira.createCriteria().andEqualTo(sqlReportCode, reportCode)
                                            .andEqualTo(sqlVersionId, versionId)
                                            .andEqualTo("issuesKey", jiraIssues.getIssuesKey());
                                    List<ReportJira> reportJiraList = reportJiraMapper.selectByExample(exampleReportJira);
                                    // 更新或插入ReportJira
                                    ReportJira entity = new ReportJira();
                                    entity.setIssuesStatus(jiraIssues.getIssuesStatu());
                                    if (reportJiraList != null && !reportJiraList.isEmpty()) {
                                        // 设置更新人和时间
                                        entity.setUpdateBy("JIRA");
                                        entity.setUpdateTime(new Date());
                                        reportJiraMapper.updateByExampleSelective(entity, exampleReportJira);
                                    } else {
                                        entity.setId(idGenerator.nextId());
                                        entity.setReportCode(reportCode);
                                        entity.setVersionId(versionId);
                                        entity.setVersionName(jiraInfo.getName());
                                        entity.setVersionRemark(jiraInfo.getVersionDescription());
                                        entity.setIssuesKey(jiraIssues.getIssuesKey());
                                        entity.setIssuesName("【" + jiraIssues.getIssuesKey() + "】" + jiraIssues.getIssuesName());
                                        entity.setAssignee(jiraIssues.getAssignee());
                                        // 设置创建人和时间
                                        entity.setCreateBy("JIRA");
                                        entity.setCreateTime(new Date());
                                        reportJiraMapper.insert(entity);
                                    }
                                }
                            }
                        }
                    } else {
                        Assert.isTrue(false, "JIRA版本对应故事为空，请添加");
                    }
                }
            }
        }
    }

    /**
     * 关闭job
     *
     * @param jobName
     * @param groupName
     * @param reportCode
     */

    private void closeJob(String jobName, String groupName, String reportCode) {
        // job参数
        String jobNameClose = jobName + "_" + reportCode;
        String groupNameClose = groupName + "_" + reportCode;
        String triggerName = jobNameClose + BaseConstants.TRIGGER_NAME_SUFFIX;
        String triggerGroupName = groupNameClose + BaseConstants.TRIGGER_GROUP_SUFFIX;
        // 关闭JIRA相关job
        try {
            logger.info("starting to stop Quartz Job...");
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
            //停止触发器
            scheduler.pauseTrigger(triggerKey);
            //移除触发器
            boolean ok = scheduler.unscheduleJob(triggerKey);
            logger.info("stop Quartz Job result:{} ", ok);
            //删除任务
            ok = scheduler.deleteJob(new JobKey(jobNameClose, groupNameClose));
            logger.info("delete Quartz Job result:{} ", ok);
        } catch (SchedulerException se) {
            logger.error("execute SchedulerException:jobName/{}, groupNmae/{}\n{}", jobNameClose, groupNameClose, se);
        }

        // 执行历史增加
        JobHistory jobHistory = new JobHistory();
        jobHistory.setId(idGenerator.nextId());
        jobHistory.setJobId(jobExecuteInfo.getJobInfoJira().getId());
        jobHistory.setJobName(jobNameClose);
        jobHistory.setGroupName(groupNameClose);
        jobHistory.setJobCorn(jobExecuteInfo.getJobInfoJira().getJobCorn());
        jobHistory.setJobUrl(jobExecuteInfo.getJobInfoJira().getJobUrl());
        jobHistory.setJobParam("关掉任务");
        jobHistory.setCreateBy("123");
        jobHistory.setCreateTime(new Date());
        jobHistory.setUpdateBy("123");
        jobHistory.setUpdateTime(new Date());
        jobHistoryMapper.insert(jobHistory);

    }

    /**
     * 启动任务获得TESTLINK的SIT/REG数据
     *
     * @return
     */
    private void executeTestLinkJob(String reportCode, List<SelectedVo> testplanList) {
        if (testplanList != null && !testplanList.isEmpty()) {
            // job参数
            String jobName = jobExecuteInfo.getJobInfoTestLink().getJobName() + "_" + reportCode;
            String groupName = jobExecuteInfo.getJobInfoTestLink().getGroupName() + "_" + reportCode;
            String description = jobExecuteInfo.getJobInfoTestLink().getJobDesc();
            String jobCorn = jobExecuteInfo.getJobInfoTestLink().getJobCorn();

            // jobDetail创建
            JobDetail jobDetail = JobBuilder
                    .newJob(TestLinkJob.class)
                    // job类和组
                    .withIdentity(jobName, groupName)
                    // 描述
                    .withDescription(description)
                    .build();

            // trigger创建
            String triggerName = jobName + BaseConstants.TRIGGER_NAME_SUFFIX;
            String triggerGroup = groupName + BaseConstants.TRIGGER_GROUP_SUFFIX;
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerName, triggerGroup)
                    // 调度规则
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobCorn))
                    .build();
            try {
                scheduler.scheduleJob(jobDetail, trigger);
            } catch (SchedulerException se) {
                logger.error("ReportInfoServiceImpl.executeTestLinkJob SchedulerException:", se);
            }

            // 执行历史增加
            JobHistory jobHistory = new JobHistory();
            jobHistory.setId(idGenerator.nextId());
            jobHistory.setJobId(jobExecuteInfo.getJobInfoJira().getId());
            jobHistory.setJobName(jobName);
            jobHistory.setGroupName(groupName);
            jobHistory.setJobCorn(jobExecuteInfo.getJobInfoJira().getJobCorn());
            jobHistory.setJobUrl(jobExecuteInfo.getJobInfoJira().getJobUrl());
            jobHistory.setJobParam("开启TESTLINK任务");
            jobHistory.setCreateBy("123");
            jobHistory.setCreateTime(new Date());
            jobHistory.setUpdateBy("123");
            jobHistory.setUpdateTime(new Date());
            jobHistoryMapper.insert(jobHistory);
        }
    }

    /**
     * 启动任务获得Jira的版本数据
     *
     * @return
     */
    private void executeJiraJob(String reportCode, List<Long> versionIdList) {
        if (versionIdList != null && !versionIdList.isEmpty()) {
            // job参数
            String jobName = jobExecuteInfo.getJobInfoJira().getJobName() + "_" + reportCode;
            String groupName = jobExecuteInfo.getJobInfoJira().getGroupName() + "_" + reportCode;
            String description = jobExecuteInfo.getJobInfoJira().getJobDesc();
            String jobCorn = jobExecuteInfo.getJobInfoJira().getJobCorn();
            // jobDetail创建
            JobDetail jobDetail = JobBuilder
                    .newJob(JiraJob.class)
                    // job类和组
                    .withIdentity(jobName, groupName)
                    // 描述
                    .withDescription(description)
                    .build();

            // trigger创建
            String triggerName = jobName + BaseConstants.TRIGGER_NAME_SUFFIX;
            String triggerGroup = groupName + BaseConstants.TRIGGER_GROUP_SUFFIX;
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerName, triggerGroup)
                    // 调度规则
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobCorn))
                    .build();
            try {
                scheduler.scheduleJob(jobDetail, trigger);
            } catch (SchedulerException se) {
                logger.error("ReportInfoServiceImpl.executeJiraJob SchedulerException:", se);
            }

            // 执行历史增加
            JobHistory jobHistory = new JobHistory();
            jobHistory.setId(idGenerator.nextId());
            jobHistory.setJobId(jobExecuteInfo.getJobInfoJira().getId());
            jobHistory.setJobName(jobName);
            jobHistory.setGroupName(groupName);
            jobHistory.setJobCorn(jobExecuteInfo.getJobInfoJira().getJobCorn());
            jobHistory.setJobUrl(jobExecuteInfo.getJobInfoJira().getJobUrl());
            jobHistory.setJobParam("开启JIRA任务");
            jobHistory.setCreateBy("123");
            jobHistory.setCreateTime(new Date());
            jobHistory.setUpdateBy("123");
            jobHistory.setUpdateTime(new Date());
            jobHistoryMapper.insert(jobHistory);
        }
    }

    /**
     * 判断AppName是否存在
     *
     * @param reportInfoTagVoList
     */
    private void isAppNameExist(List<ReportInfoTagVo> reportInfoTagVoList) {
        // 测试报告TAG信息存在时判断项目是否存在
        if (reportInfoTagVoList != null && !reportInfoTagVoList.isEmpty()) {
            // 将所有项目名放入链表
            List<String> appNameList = new ArrayList<>();
            for (ReportInfoTagVo reportInfoTagVo : reportInfoTagVoList) {
                appNameList.add(reportInfoTagVo.getAppName());
            }
            // 根据用户名查询数据库项目是否存在
            Example example = new Example(AppInfo.class);
            example.createCriteria().andIn("appName", appNameList);
            List<AppInfo> appInfoList = appInfoMapper.selectByExample(example);
            // 查找出项目时，判断是否所有项目都存在
            if (appInfoList != null && !appInfoList.isEmpty()) {
                // 将查找出的所有项目数据按照key=appName,value=appInfo信息保存
                Map<String, AppInfo> map = new HashMap<>();
                for (AppInfo appInfo : appInfoList) {
                    map.put(appInfo.getAppName(), appInfo);
                }
                // 通过项目名拉取项目数据，未拉取到时表示该项目不存在，不存在时返回错误信息
                for (String appName : appNameList) {
                    Assert.isTrue(NullUtil.isNotEmpty(map.get(appName)),
                            "项目" + appName + "不存在");
                }
            } else {
                // 未查找出项目时直接返回信息
                Assert.isTrue(false, "所有项目均不存在");
            }
        }
    }

    /**
     * 判断AppName是否重复
     *
     * @param reportInfoTagVoList
     */
    private void isAppNameRepeat(List<ReportInfoTagVo> reportInfoTagVoList) {
        if (reportInfoTagVoList != null && !reportInfoTagVoList.isEmpty()) {
            Map<String, ReportInfoTagVo> map = new HashMap<>();
            for (ReportInfoTagVo reportInfoTagVo : reportInfoTagVoList) {
                ReportInfoTagVo reportInfoTagVo1 = map.get(reportInfoTagVo.getAppName());
                if (reportInfoTagVo1 != null) {
                    Assert.isTrue(false, "测试通过的tag信息应用名" + reportInfoTagVo1.getAppName() + "重复");
                } else {
                    map.put(reportInfoTagVo.getAppName(), reportInfoTagVo);
                }
            }
        }

    }

    /**
     * 插入testlink信息，并启动job
     *
     * @param reportTestLinkVoList TESTLINK插入数据
     * @param reportCode           测试报告code
     * @param title                测试报告名称
     */
    private void insertTestLinkAndCreateJob(List<ReportTestLinkVo> reportTestLinkVoList, String reportCode, String title) {
        if (null != reportTestLinkVoList && !reportTestLinkVoList.isEmpty()) {
            // 验证测试计划系统名称、版本
            testLinkParamCheck(reportTestLinkVoList);

            Map<String, String> isCloseMap = new HashMap<>();
            List<SelectedVo> testplanList = new ArrayList<>();
            List<Long> versonIdList = new ArrayList<>();
            for (ReportTestLinkVo reportTestLinkVo : reportTestLinkVoList) {
                // TESTLINK项目名
                Assert.isTrue(StringUtils.isNotBlank(reportTestLinkVo.getTprjname()), "TESTLINK项目名为空");
                // TESTLINK项目名的测试计划
                Assert.isTrue(StringUtils.isNotBlank(reportTestLinkVo.getTestplanid()), "TESTLINK测试计划为空");
                // JIRA版本名
                Assert.isTrue(StringUtils.isNotBlank(reportTestLinkVo.getVersionName()), "JIRA版本名为空");
                // 查询测试报告状况，判断插入或者更新
                ReportTestLink reportTestLinkSelect = new ReportTestLink();
                reportTestLinkSelect.setVersionName(reportTestLinkVo.getVersionName());
                reportTestLinkSelect.setTprjname(reportTestLinkVo.getTprjname());
                List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.select(reportTestLinkSelect);
                // 保存新建tprjname
                isCloseMap.put(reportTestLinkVo.getTprjname(), reportTestLinkVo.getVersionName() + "_" + title);
                SelectedVo selectedVo = new SelectedVo();
                if (reportTestLinkList != null && !reportTestLinkList.isEmpty()) {
                    // 如果有存在同样TESTLINK项目、版本则拉取本地的数据库的历史testplanid
                    selectedVo.setCode(reportTestLinkList.get(0).getTestplanid());
                    selectedVo.setName(reportTestLinkList.get(0).getTprjname());
                    Example example = new Example(ReportTestLink.class);
                    example.createCriteria().andEqualTo("versionName", reportTestLinkVo.getVersionName())
                            .andEqualTo("tprjname", reportTestLinkVo.getTprjname());
                    ReportTestLink reportTestLink = new ReportTestLink();
                    reportTestLink.setReportCode(reportCode);
                    reportTestLinkMapper.updateByExampleSelective(reportTestLink, example);
                } else {
                    String testplanid = reportTestLinkVo.getTestplanid();
                    selectedVo.setCode(testplanid);
                    selectedVo.setName(reportTestLinkVo.getTprjname());

                    ReportTestLink reportTestLink = reportTestLinkVo.parseModel();
                    reportTestLink.setId(idGenerator.nextId());
                    reportTestLink.setReportCode(reportCode);
                    reportTestLink.setTestplanid(testplanid);
                    reportTestLink.setCreateBy("123");
                    reportTestLink.setCreateTime(new Date());
                    reportTestLink.setUpdateBy("123");
                    reportTestLink.setUpdateTime(new Date());
                    reportTestLinkMapper.insert(reportTestLink);
                }
                Long versonId = reportTestLinkVo.getVersionId();
                versonIdList.add(versonId);
                testplanList.add(selectedVo);

            }
            // 开启调度
            executeTestLinkJob(reportCode, testplanList);
            executeJiraJob(reportCode, versonIdList);
        } else {
            // 当tag信息删除完时报错
            Assert.isTrue(false, "测试计划信息为空");
        }
    }

    /**
     * 验证测试计划系统名称、版本
     *
     * @param reportTestLinkVoList
     */
    private void testLinkParamCheck(List<ReportTestLinkVo> reportTestLinkVoList) {
        List<String> tprjidList = new ArrayList<>();
        List<String> versionIdList = new ArrayList<>();
        for (ReportTestLinkVo reportTestLinkVo : reportTestLinkVoList) {
            if (tprjidList.contains(reportTestLinkVo.getTprjid())) {
                Assert.isTrue(false, "测试计划系统名称重复选择");
            }
            tprjidList.add(reportTestLinkVo.getTprjid());
            if (versionIdList.contains(reportTestLinkVo.getVersionName())) {
                Assert.isTrue(false, "测试计划版本重复选择");
            }
            versionIdList.add(reportTestLinkVo.getVersionName());
        }
        Example example = new Example(ReportTestLink.class);
        example.createCriteria().andIn("versionId", versionIdList);
        List<ReportTestLink> reportTestLinkList2 = reportTestLinkMapper.selectByExample(example);
        if (reportTestLinkList2 != null && !reportTestLinkList2.isEmpty()) {
            Assert.isTrue(false, "测试计划版本已被其他测试报告选择");
        }


    }

    /**
     * 更新或者插入ReportTag
     *
     * @param reportInfoTagVoList
     */
    private void updateOrInsertReportTag(List<ReportInfoTagVo> reportInfoTagVoList, String reportCode) {
        if (null != reportInfoTagVoList && !reportInfoTagVoList.isEmpty()) {
            // 判断TAG保存项目是否存在0
            isAppNameExist(reportInfoTagVoList);
            // 判断TAG保存项目是否重复
            isAppNameRepeat(reportInfoTagVoList);
            for (ReportInfoTagVo reportInfoTagVo : reportInfoTagVoList) {
                // 将vo转换成bean
                ReportInfoTag reportInfoTag = reportInfoTagVo.parseModel();
                // ID不存在时该从信息属于新增，ID存在时该从信息属于更新
                if (reportInfoTag.getId() == null) {
                    // 设置报告编号
                    reportInfoTag.setReportCode(reportCode);
                    // 设置ID
                    reportInfoTag.setId(idGenerator.nextId());
                    // 设置更新人和时间
                    reportInfoTag.setCreateBy("123");
                    reportInfoTag.setCreateTime(new Date());
                    reportInfoTag.setUpdateBy("123");
                    reportInfoTag.setUpdateTime(new Date());
                    reportInfoTagMapper.insert(reportInfoTag);

                } else {
                    // 设置更新人和时间
                    reportInfoTag.setUpdateBy("123");
                    reportInfoTag.setUpdateTime(new Date());
                    // 更新唯一条件id
                    Example example = new Example(ReportInfoTag.class);
                    example.createCriteria().andEqualTo("id", reportInfoTagVo.getId());
                    reportInfoTagMapper.updateByExampleSelective(reportInfoTag, example);
                }

            }
        } else {
            // 当tag信息删除完时报错
            Assert.isTrue(false, "测试通过的Tag信息为空");
        }
    }

    /**
     * 更新测试负责人
     *
     * @param reportJiraVoList
     * @param reportCode
     */
    private void updateTestJiraLeader(List<ReportJiraVo> reportJiraVoList, String reportCode) {
        Example example = new Example(ReportJira.class);
        example.createCriteria().andEqualTo(sqlReportCode, reportCode);
        List<ReportJira> reportJiraList = reportJiraMapper.selectByExample(example);
        if (reportJiraList != null && !reportJiraList.isEmpty() && reportJiraVoList != null && !reportJiraVoList.isEmpty()) {
            if (reportJiraList.size() != reportJiraVoList.size()) {
                Assert.isTrue(false, "Jira有更新，请重新填写测试责任人");
            } else {
                // 查询所有版本状态
                for (ReportJiraVo reportJiraVo : reportJiraVoList) {
                    Assert.isTrue(StringUtils.isNotBlank(reportJiraVo.getTestLeader()), "需求结果汇总存在测试负责人为空");
                    example.clear();
                    example.createCriteria().andEqualTo(sqlReportCode, reportCode)
                            .andEqualTo(sqlVersionId, reportJiraVo.getVersionId())
                            .andEqualTo("issuesKey", reportJiraVo.getIssuesKey());
                    // 插入ReportJira
                    ReportJira entity = new ReportJira();
                    entity.setTestLeader(reportJiraVo.getTestLeader());
                    // 设置更新人和时间
                    entity.setUpdateBy("JIRA");
                    entity.setUpdateTime(new Date());
                    reportJiraMapper.updateByExampleSelective(entity, example);
                }
            }
        }
    }

    /**
     * 判断名字重复
     *
     * @param title
     * @return
     */
    private boolean isRepeat(String title, String reportCode) {
        if (StringUtils.isNotBlank(title)) {
            Example example = new Example(ReportInfo.class);
            example.createCriteria().andNotEqualTo(sqlReportCode, reportCode).andEqualTo(sqlTitle, title.trim());
            List<ReportInfo> reportInfoList = reportInfoMapper.selectByExample(example);
            if (reportInfoList != null && !reportInfoList.isEmpty()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 文件上传
     *
     * @param file
     * @return
     */
    @Override
    public FileUploadVo fileUpload(MultipartFile file) {
        return DCFileUtil.fileUpload(file, filePathInfo.getReportPath());
    }

    /**
     * 删除文件
     *
     * @param fileId
     * @return
     */
    @Override
    public Integer fileDelete(String fileId) {
        return DCFileUtil.fileDelete(fileId, filePathInfo.getReportPath());
    }

    /**
     * 文件下载
     *
     * @param fileId
     * @param response
     */
    @Override
    public void downloadFile(long fileId, HttpServletResponse response) {
        ReportFiles reportFiles = new ReportFiles();
        reportFiles.setId(fileId);
        reportFiles = reportFilesMapper.selectOne(reportFiles);
        File file = new File(reportFiles.getFileUrl() + File.separator + reportFiles.getFileName());
        convertUtil.outputResponse(reportFiles.getFileName(), file, Integer.parseInt(String.valueOf(file.length())), response);
    }

    /**
     * 获取测试计划
     *
     * @param reportInfoRequest
     * @return
     */
    @Override
    public List<SelectedVo> getTestPlan(ReportInfoRequest reportInfoRequest) {
        // 用id获取name
        List<SelectedVo> selectedVoTprjList = getTestLink(null);
        String tprjname = null;
        for (SelectedVo selectedVoTprj : selectedVoTprjList) {
            if (selectedVoTprj.getCode().equalsIgnoreCase(reportInfoRequest.getTprjname())) {
                tprjname = selectedVoTprj.getName();
                break;
            }
        }

        // 获取已经使用过的testplan
        Example example = new Example(ReportTestLink.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andNotEqualTo(sqlReportCode, NO_USE);
        if (StringUtils.isNotBlank(reportInfoRequest.getParentCode())) {
            criteria.andNotEqualTo(sqlReportCode, reportInfoRequest.getParentCode());
        }
        List<ReportTestLink> reportTestLinkList = reportTestLinkMapper.selectByExample(example);
        Map<String, String> map = new HashMap<>();
        for (ReportTestLink reportTestLink1 : reportTestLinkList) {
            map.put(reportTestLink1.getTestplanid(), reportTestLink1.getTprjid());
        }

        List<SelectedVo> selectedVoList = new ArrayList<>();
        // 访问url获取数据
        String url = testLinkInfo.getHost() + testLinkInfo.getGetprojecttestplans() + tprjname;
        logger.info("ReportInfoServiceImpl.getTestPlan call url:{}", url);
        ResponseEntity<String> responseEntity = restTemplate.exchange(url,
                HttpMethod.POST, null, String.class);
        String responseEntityStr = GsonUtils.getInstance().toJson(responseEntity);
        logger.info("ReportInfoServiceImpl.getTestPlan return result:{}", responseEntityStr);
        String bodyStr = responseEntity.getBody();
        JSONObject bodyJson = JSONObject.parseObject(bodyStr);

        // 数据转换
        if (bodyJson != null && !bodyJson.isEmpty()) {
            JSONArray bodyJsonArray = (JSONArray) bodyJson.get("testplans");
            if (bodyJsonArray != null && !bodyJsonArray.isEmpty()) {
                for (int i = 0; i < bodyJsonArray.size(); i++) {
                    JSONObject jsonObject = (JSONObject) bodyJsonArray.get(i);
                    String code = String.valueOf(jsonObject.get("id"));
                    String name = String.valueOf(jsonObject.get("name"));
                    if (map.get(code) == null) {
                        SelectedVo selectedVo = new SelectedVo();
                        selectedVo.setCode(code);
                        selectedVo.setName(name);
                        selectedVoList.add(selectedVo);
                    }
                }
            }
        }
        return selectedVoList;
    }

    /**
     * 生成pdf
     *
     * @param reportCode
     * @return
     */
    @Override
    public String getPdf(String reportCode) {
        Assert.isTrue(StringUtils.isNotBlank(reportCode), "测试报告编码为空");
        // 获取测试报告数据
        ReportInfoRequest request = new ReportInfoRequest();
        request.setReportCode(reportCode);
        ReportInfoVo reportInfoVo = getOne(request);

        PdfWriter writer = null;
        Document doc = null;
        FileOutputStream out = null;
        //  生成地址配置
        String url = filePathInfo.getPdfPath() + "/" + reportInfoVo.getTitle() + ".pdf";
        File content = new File(filePathInfo.getPdfPath());
        if (!content.exists()) {
            content.mkdirs();
        }
        try {
            doc = new Document();
            out = new FileOutputStream(url);
            writer = PdfWriter.getInstance(doc, out);
            Header header = new Header("测试报告", "测试报告");
            writer.add(header);

            // 打开文档
            doc.open();
            doc.newPage();

            BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
            Font font = new Font(bfChinese, 8, Font.NORMAL);

            Paragraph titleStr = new Paragraph("基本信息", font);
            doc.add(titleStr);
            Paragraph title = new Paragraph(reportInfoVo.getTitle(), font);
            doc.add(title);

            doc.add(new Paragraph("\n"));
            Paragraph reportResultStr = new Paragraph("测试结论", font);
            doc.add(reportResultStr);
            Paragraph reportResult = new Paragraph(reportInfoVo.getReportResult(), font);
            doc.add(reportResult);

            doc.add(new Paragraph("\n"));
            Paragraph testlinkStr = new Paragraph("发布版本列表", font);
            doc.add(testlinkStr);
            PdfPTable testlinkTable = new PdfPTable(3);
            PdfPCell cellNo = new PdfPCell(new Paragraph("序号", font));
            testlinkTable.addCell(cellNo);
            PdfPCell cellTestLink = new PdfPCell(new Paragraph("系统名称", font));
            testlinkTable.addCell(cellTestLink);
            PdfPCell cellVersion = new PdfPCell(new Paragraph("版本", font));
            testlinkTable.addCell(cellVersion);
            for (int i = 0; i < reportInfoVo.getReportTestLinkVoList().size(); i++) {
                ReportTestLinkVo reportTestLinkVo = reportInfoVo.getReportTestLinkVoList().get(i);
                testlinkTable.addCell(String.valueOf(i + 1));
                PdfPCell tprjname = new PdfPCell(new Paragraph(reportTestLinkVo.getTprjname(), font));
                testlinkTable.addCell(tprjname);
                PdfPCell versionName = new PdfPCell(new Paragraph(reportTestLinkVo.getVersionName(), font));
                testlinkTable.addCell(versionName);
            }
            doc.add(testlinkTable);

            doc.add(new Paragraph("\n"));
            Paragraph jiraStr = new Paragraph("需求及验收结果", font);
            doc.add(jiraStr);
            PdfPTable jiraTable = new PdfPTable(6);
            PdfPCell cellJiraNo = new PdfPCell(new Paragraph("序号", font));
            jiraTable.addCell(cellJiraNo);
            PdfPCell cellTestLeader = new PdfPCell(new Paragraph("系统名称", font));
            jiraTable.addCell(cellTestLeader);
            PdfPCell cellJiraVersion = new PdfPCell(new Paragraph("版本", font));
            jiraTable.addCell(cellJiraVersion);
            PdfPCell cellStory = new PdfPCell(new Paragraph("需求", font));
            jiraTable.addCell(cellStory);
            PdfPCell cellJiraResult = new PdfPCell(new Paragraph("验收结果", font));
            jiraTable.addCell(cellJiraResult);
            PdfPCell cellJiraPerson = new PdfPCell(new Paragraph("产品验收人", font));
            jiraTable.addCell(cellJiraPerson);
            for (int i = 0; i < reportInfoVo.getReportJiraVoList().size(); i++) {
                ReportJiraVo reportJiraVo = reportInfoVo.getReportJiraVoList().get(i);
                jiraTable.addCell(String.valueOf(i + 1));
                PdfPCell cellTestLeaderStr = new PdfPCell(new Paragraph(reportJiraVo.getTestLeader(), font));
                jiraTable.addCell(cellTestLeaderStr);
                PdfPCell cellJiraVersionStr = new PdfPCell(new Paragraph(reportJiraVo.getVersionName(), font));
                jiraTable.addCell(cellJiraVersionStr);
                PdfPCell cellStoryStr = new PdfPCell(new Paragraph(reportJiraVo.getIssuesName(), font));
                jiraTable.addCell(cellStoryStr);
                PdfPCell cellJiraResultStr = new PdfPCell(new Paragraph(reportJiraVo.getIssuesStatus(), font));
                jiraTable.addCell(cellJiraResultStr);
                PdfPCell cellJiraPersonStr = new PdfPCell(new Paragraph(reportJiraVo.getAssignee(), font));
                jiraTable.addCell(cellJiraPersonStr);
            }
            doc.add(jiraTable);

            doc.add(new Paragraph("\n"));
            Paragraph sitResultStr = new Paragraph("功能测试结果汇总", font);
            doc.add(sitResultStr);
            Paragraph sitTime = new Paragraph("功能测试开始时间" + reportInfoVo.getSitTimeStart() + "\t\t功能测试结束时间" + reportInfoVo.getSitTimeEnd(), font);
            doc.add(sitTime);
            Paragraph sitResult = new Paragraph(reportInfoVo.getSitResult(), font);
            doc.add(sitResult);

            doc.add(new Paragraph("\n"));
            Paragraph retResultStr = new Paragraph("回归测试结果汇总", font);
            doc.add(retResultStr);
            Paragraph retTime = new Paragraph("回归测试开始时间" + reportInfoVo.getRetTimeStart() + "\t\t回归测试结束时间" + reportInfoVo.getRetTimeEnd(), font);
            doc.add(retTime);
            Paragraph retResult = new Paragraph(reportInfoVo.getRetResult(), font);
            doc.add(retResult);

            doc.add(new Paragraph("\n"));
            Paragraph uatResultStr = new Paragraph("验收测试(UAT)结果汇总", font);
            doc.add(uatResultStr);
            Paragraph uatTime = new Paragraph("验收测试始时间" + reportInfoVo.getUatTimeStart() + "验收测试结束时间" + reportInfoVo.getUatTimeEnd(), font);
            doc.add(uatTime);
            Paragraph uatResult = new Paragraph(reportInfoVo.getUatResult(), font);
            doc.add(uatResult);

            doc.add(new Paragraph("\n"));
            Paragraph bugRemarkStr = new Paragraph("Bug概述", font);
            doc.add(bugRemarkStr);
            Paragraph bugRemark = new Paragraph(reportInfoVo.getBugRemark(), font);
            doc.add(bugRemark);

            doc.add(new Paragraph("\n"));
            Paragraph tagInfo = new Paragraph("测试通过的Tag信息", font);
            doc.add(tagInfo);
            PdfPTable tagTable = new PdfPTable(4);
            PdfPCell cellTagNo = new PdfPCell(new Paragraph("序号", font));
            tagTable.addCell(cellTagNo);
            PdfPCell cellAppNameStr = new PdfPCell(new Paragraph("应用名", font));
            tagTable.addCell(cellAppNameStr);
            PdfPCell cellLevelStr = new PdfPCell(new Paragraph("优先级(数字越小优先级越高)", font));
            tagTable.addCell(cellLevelStr);
            PdfPCell cellTagInfoStr = new PdfPCell(new Paragraph("TAG", font));
            tagTable.addCell(cellTagInfoStr);
            for (int i = 0; i < reportInfoVo.getReportInfoTagsVoList().size(); i++) {
                ReportInfoTagVo reportInfoTagVo = reportInfoVo.getReportInfoTagsVoList().get(i);
                tagTable.addCell(String.valueOf(i + 1));
                PdfPCell cellAppName = new PdfPCell(new Paragraph(reportInfoTagVo.getAppName(), font));
                tagTable.addCell(cellAppName);
                PdfPCell cellLevel = new PdfPCell(new Paragraph(String.valueOf(reportInfoTagVo.getLevel()), font));
                tagTable.addCell(cellLevel);
                PdfPCell cellTagInfo = new PdfPCell(new Paragraph(reportInfoTagVo.getTagInfo(), font));
                tagTable.addCell(cellTagInfo);
            }
            doc.add(tagTable);

            doc.add(new Paragraph("\n"));
            Paragraph file = new Paragraph("上线手册或者其他必要文件", font);
            doc.add(file);
            PdfPTable fileTable = new PdfPTable(2);
            PdfPCell cellFileNo = new PdfPCell(new Paragraph("序号", font));
            fileTable.addCell(cellFileNo);
            PdfPCell fileName = new PdfPCell(new Paragraph("文档名称", font));
            fileTable.addCell(fileName);
            for (int i = 0; i < reportInfoVo.getFileList().size(); i++) {
                FileUploadVo fileUploadVo = reportInfoVo.getFileList().get(i);
                jiraTable.addCell(String.valueOf(i + 1));
                PdfPCell cellFileName = new PdfPCell(new Paragraph(fileUploadVo.getFileName(), font));
                jiraTable.addCell(cellFileName);
            }
            doc.add(fileTable);

        } catch (Exception e) {
            logger.error("getPdf Exception", e);
        } finally {
            if (doc != null) {
                try {
                    doc.close();
                } catch (Exception e) {
                    logger.error("doc close IOException", e);
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    logger.error("out close IOException", e);
                }
            }
            if (writer != null) {
                try {
                    writer.close();
                } catch (Exception e) {
                    logger.error("writer close IOException", e);
                }
            }
        }
        Assert.isTrue(new File(url).exists(), "PDF文件生成错误");
        return url;
    }

    /**
     * 更新uat显示flag
     *
     * @param reportInfoRequest
     * @return
     */
    @Override
    public Integer updateUatFlag(ReportInfoRequest reportInfoRequest) {
        Assert.isTrue(StringUtils.isNotBlank(reportInfoRequest.getReportCode()), "测试报告编码为空");
        Assert.isTrue(StringUtils.isNotBlank(reportInfoRequest.getUatFlag()), "测试报告UAT显示FLAG为空");
        Example example = new Example(ReportInfo.class);
        example.createCriteria().andEqualTo(sqlReportCode, reportInfoRequest.getReportCode());
        ReportInfo reportInfo = new ReportInfo();
        reportInfo.setUatFlag(reportInfoRequest.getUatFlag());
        return reportInfoMapper.updateByExampleSelective(reportInfo, example);

    }


}